//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package org_forum_api_serv

import (
	"context"
	"fmt"
	"time"

	"atomgit.com/openlinksaas-org/api-server/bg_runner/tasks"
	"atomgit.com/openlinksaas-org/api-server/dao"
	"atomgit.com/openlinksaas-org/api-server/dao/fs_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/org_dao"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/fs_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/org_forum_api"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *OrgForumApiImpl) CreateForum(ctx context.Context, req *org_forum_api.CreateForumRequest) (*org_forum_api.CreateForumResponse, error) {
	if req.OrgForumPerm == nil {
		req.OrgForumPerm = &org_forum_api.OrgForumPerm{
			AllowCreateThreadForAll: true,
			CreateThreadUserIdList:  []string{},
			AllowReplyThreadForAll:  true,
			ReplyThreadUserIdList:   []string{},
		}
	}
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_forum_api.CreateForumResponse{
			Code:   org_forum_api.CreateForumResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	orgItem, err := org_dao.OrgInfoDao.Get(ctx, req.OrgId)
	if err != nil {
		return &org_forum_api.CreateForumResponse{
			Code:   org_forum_api.CreateForumResponse_CODE_NO_ORG,
			ErrMsg: "组织不存在",
		}, nil
	}

	if orgItem.OwnerUserId != sessionItem.UserId {
		return &org_forum_api.CreateForumResponse{
			Code:   org_forum_api.CreateForumResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	forumId := uuid.NewString()
	fsId := uuid.NewString()
	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		//创建文件系统
		err = fs_dao.FsInfoDao.Insert(sessCtx, &fs_dao.FsInfoDbItem{
			FsId:      fsId,
			OwnerType: int32(fs_api.FS_OWNER_TYPE_FS_OWNER_TYPE_ORG),
			OwnerId:   req.OrgId,
			Status: fs_dao.FsStatusDbItem{
				FileCount:     0,
				TotalFileSize: 0,
			},
		})
		if err != nil {
			return nil, err
		}
		//创建论坛
		err = org_dao.ForumDao.Insert(sessCtx, &org_dao.OrgForumInfoDbItem{
			ForumId:     forumId,
			ForumName:   req.ForumName,
			OrgId:       req.OrgId,
			Weight:      req.Weight,
			FsId:        fsId,
			ThreadCount: 0,
			OrgForumPerm: org_dao.OrgForumPermDbItem{
				AllowCreateThreadForAll: req.OrgForumPerm.AllowCreateThreadForAll,
				CreateThreadUserIdList:  req.OrgForumPerm.CreateThreadUserIdList,
				AllowReplyThreadForAll:  req.OrgForumPerm.AllowReplyThreadForAll,
				ReplyThreadUserIdList:   req.OrgForumPerm.ReplyThreadUserIdList,
			},
			TimeStamp: nowTime,
		})
		if err != nil {
			return nil, err
		}
		return &org_forum_api.CreateForumResponse{
			Code:    org_forum_api.CreateForumResponse_CODE_OK,
			ForumId: forumId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*org_forum_api.CreateForumResponse), nil
}

func (apiImpl *OrgForumApiImpl) UpdateForum(ctx context.Context, req *org_forum_api.UpdateForumRequest) (*org_forum_api.UpdateForumResponse, error) {
	if req.OrgForumPerm == nil {
		req.OrgForumPerm = &org_forum_api.OrgForumPerm{
			AllowCreateThreadForAll: true,
			CreateThreadUserIdList:  []string{},
			AllowReplyThreadForAll:  true,
			ReplyThreadUserIdList:   []string{},
		}
	}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_forum_api.UpdateForumResponse{
			Code:   org_forum_api.UpdateForumResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	orgItem, err := org_dao.OrgInfoDao.Get(ctx, req.OrgId)
	if err != nil {
		return &org_forum_api.UpdateForumResponse{
			Code:   org_forum_api.UpdateForumResponse_CODE_NO_ORG,
			ErrMsg: "组织不存在",
		}, nil
	}

	if orgItem.OwnerUserId != sessionItem.UserId {
		return &org_forum_api.UpdateForumResponse{
			Code:   org_forum_api.UpdateForumResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err := org_dao.ForumDao.Exist(ctx, req.OrgId, req.ForumId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_forum_api.UpdateForumResponse{
			Code:   org_forum_api.UpdateForumResponse_CODE_NO_FORUM,
			ErrMsg: "讨论组不存在",
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = org_dao.ForumDao.Update(sessCtx, req.OrgId, req.ForumId, req.ForumName, req.Weight,
			&org_dao.OrgForumPermDbItem{
				AllowCreateThreadForAll: req.OrgForumPerm.AllowCreateThreadForAll,
				CreateThreadUserIdList:  req.OrgForumPerm.CreateThreadUserIdList,
				AllowReplyThreadForAll:  req.OrgForumPerm.AllowReplyThreadForAll,
				ReplyThreadUserIdList:   req.OrgForumPerm.ReplyThreadUserIdList,
			}, nowTime)
		if err != nil {
			return nil, err
		}
		return &org_forum_api.UpdateForumResponse{
			Code: org_forum_api.UpdateForumResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*org_forum_api.UpdateForumResponse), nil
}

func (apiImpl *OrgForumApiImpl) ListForum(ctx context.Context, req *org_forum_api.ListForumRequest) (*org_forum_api.ListForumResponse, error) {
	emptyList := []*org_forum_api.OrgForumInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_forum_api.ListForumResponse{
			Code:      org_forum_api.ListForumResponse_CODE_WRONG_SESSION,
			ErrMsg:    "会话不存在",
			ForumList: emptyList,
		}, nil
	}
	exist, err := org_dao.OrgInfoDao.Exist(ctx, req.OrgId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_forum_api.ListForumResponse{
			Code:      org_forum_api.ListForumResponse_CODE_NO_ORG,
			ErrMsg:    "组织不存在",
			ForumList: emptyList,
		}, nil
	}
	exist, err = org_dao.MemberDao.Exist(ctx, req.OrgId, sessionItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_forum_api.ListForumResponse{
			Code:      org_forum_api.ListForumResponse_CODE_NO_PERMISSION,
			ErrMsg:    "没有权限",
			ForumList: emptyList,
		}, nil
	}

	forumItemList, err := org_dao.ForumDao.List(ctx, req.OrgId)
	if err != nil {
		return nil, err
	}
	forumList := []*org_forum_api.OrgForumInfo{}
	for _, forumItem := range forumItemList {
		forum := forumItem.ToOrgForumInfo(sessionItem.UserId)
		forumList = append(forumList, forum)
	}
	return &org_forum_api.ListForumResponse{
		Code:      org_forum_api.ListForumResponse_CODE_OK,
		ForumList: forumList,
	}, nil
}

func (apiImpl *OrgForumApiImpl) GetForum(ctx context.Context, req *org_forum_api.GetForumRequest) (*org_forum_api.GetForumResponse, error) {
	emptyInfo := &org_forum_api.OrgForumInfo{
		OrgForumPerm: &org_forum_api.OrgForumPerm{
			CreateThreadUserIdList: []string{},
			ReplyThreadUserIdList:  []string{},
		},
		UserPerm: &org_forum_api.UserPerm{},
	}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_forum_api.GetForumResponse{
			Code:      org_forum_api.GetForumResponse_CODE_WRONG_SESSION,
			ErrMsg:    "会话不存在",
			ForumInfo: emptyInfo,
		}, nil
	}
	exist, err := org_dao.OrgInfoDao.Exist(ctx, req.OrgId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_forum_api.GetForumResponse{
			Code:      org_forum_api.GetForumResponse_CODE_NO_ORG,
			ErrMsg:    "组织不存在",
			ForumInfo: emptyInfo,
		}, nil
	}
	exist, err = org_dao.MemberDao.Exist(ctx, req.OrgId, sessionItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_forum_api.GetForumResponse{
			Code:      org_forum_api.GetForumResponse_CODE_NO_PERMISSION,
			ErrMsg:    "没有权限",
			ForumInfo: emptyInfo,
		}, nil
	}

	forumItem, err := org_dao.ForumDao.Get(ctx, req.OrgId, req.ForumId)
	if err != nil {
		return &org_forum_api.GetForumResponse{
			Code:      org_forum_api.GetForumResponse_CODE_NO_FORUM,
			ErrMsg:    "讨论组不存在",
			ForumInfo: emptyInfo,
		}, nil
	}

	return &org_forum_api.GetForumResponse{
		Code:      org_forum_api.GetForumResponse_CODE_OK,
		ForumInfo: forumItem.ToOrgForumInfo(sessionItem.UserId),
	}, nil
}

func (apiImpl *OrgForumApiImpl) RemoveForum(ctx context.Context, req *org_forum_api.RemoveForumRequest) (*org_forum_api.RemoveForumResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_forum_api.RemoveForumResponse{
			Code:   org_forum_api.RemoveForumResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	orgItem, err := org_dao.OrgInfoDao.Get(ctx, req.OrgId)
	if err != nil {
		return &org_forum_api.RemoveForumResponse{
			Code:   org_forum_api.RemoveForumResponse_CODE_NO_ORG,
			ErrMsg: "组织不存在",
		}, nil
	}

	if orgItem.OwnerUserId != sessionItem.UserId {
		return &org_forum_api.RemoveForumResponse{
			Code:   org_forum_api.RemoveForumResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	forumItem, err := org_dao.ForumDao.Get(ctx, req.OrgId, req.ForumId)
	if err != nil { //记录不存在
		return &org_forum_api.RemoveForumResponse{
			Code: org_forum_api.RemoveForumResponse_CODE_OK,
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		//清除论坛对象
		err = org_dao.ForumDao.Remove(sessCtx, req.OrgId, req.ForumId)
		if err != nil {
			return nil, err
		}
		//清除会话
		err = org_dao.ForumThreadDao.RemoveByForum(sessCtx, req.OrgId, req.ForumId)
		if err != nil {
			return nil, err
		}
		//清除会话内容
		err = org_dao.ThreadContentDao.RemoveByForum(sessCtx, req.OrgId, req.ForumId)
		if err != nil {
			return nil, err
		}
		//创建清理文件系统任务
		bgTaskId := fmt.Sprintf("OrgForumFsClean:%s", req.ForumId)
		err = dao.BgTaskDao.Insert(context.Background(), bgTaskId, nowTime, nowTime+(3600*1000), &tasks.OrgForumFsClean{
			OrgId:        req.OrgId,
			ForumId:      req.ForumId,
			FsId:         forumItem.FsId,
			FsRemoteAddr: apiImpl.fsRemoteAddr,
		})
		if err != nil {
			return nil, err
		}
		return &org_forum_api.RemoveForumResponse{
			Code: org_forum_api.RemoveForumResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*org_forum_api.RemoveForumResponse), nil
}
